Use the subtype field for the custom event that is used to wake up the
authorRichard Hult <richard@imendio.com>
Sun, 24 Feb 2008 17:45:29 +0000 (17:45 +0000)
committerRichard Hult <rhult@src.gnome.org>
Sun, 24 Feb 2008 17:45:29 +0000 (17:45 +0000)
2008-02-24  Richard Hult  <richard@imendio.com>

* gdk/quartz/gdkprivate-quartz.h:
* gdk/quartz/gdkeventloop-quartz.c: (got_fd_activity), (poll_func):
Use the subtype field for the custom event that is used to wake up
the mainloop so we can have other custom event types.

* gdk/quartz/gdkevents-quartz.c:
(_gdk_quartz_events_trigger_crossing_events):
* gdk/quartz/gdkwindow-quartz.c: (show_window_internal): Create
crossing events after showing a window if necessary, to work
around problems with the tracking rect API.

svn path=/trunk/; revision=19637

ChangeLog
gdk/quartz/gdkeventloop-quartz.c
gdk/quartz/gdkevents-quartz.c
gdk/quartz/gdkprivate-quartz.h
gdk/quartz/gdkwindow-quartz.c

index 200ce17bcc6b146002db462698f6c471d262b88d..b13f6487dac76686ff86eb2bb1f545f9691c133e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-02-24  Richard Hult  <richard@imendio.com>
+
+       * gdk/quartz/gdkprivate-quartz.h:
+       * gdk/quartz/gdkeventloop-quartz.c: (got_fd_activity), (poll_func):
+       Use the subtype field for the custom event that is used to wake up
+       the mainloop so we can have other custom event types.
+
+       * gdk/quartz/gdkevents-quartz.c:
+       (_gdk_quartz_events_trigger_crossing_events):
+       * gdk/quartz/gdkwindow-quartz.c: (show_window_internal): Create
+       crossing events after showing a window if necessary, to work
+       around problems with the tracking rect API.
+
 2008-02-22  Dominic Lachowicz  <domlachowicz@gmail.com>
 
        * demos/gtk-demo/printing.c (do_printing): gtk-demo printing gives 
index bb14a13f3256318f53bd017d168df78b84581d04..dcc8c9ca914845d251fca463ab3bfdc1b19a323f 100644 (file)
@@ -139,7 +139,7 @@ got_fd_activity (void *info)
                            timestamp: 0
                         windowNumber: 0
                              context: nil
-                             subtype: 0
+                              subtype: GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
                                data1: 0 
                                data2: 0];
 
@@ -253,7 +253,8 @@ poll_func (GPollFD *ufds, guint nfds, gint timeout_)
   
   if (event)
     {
-      if ([event type] == NSApplicationDefined)
+      if ([event type] == NSApplicationDefined &&
+          [event subtype] == GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP)
         {
           pthread_mutex_lock (&pollfd_mutex);
 
index 5bc0367fdf93c42d0b570af92270754ef456064a..af37e91dc4efd494704a291c22d297ec44c0160b 100644 (file)
@@ -650,6 +650,7 @@ create_crossing_event (GdkWindow      *window,
     point = [nsevent locationInWindow];
 
     toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
+
     impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
 
     x_tmp = point.x;
@@ -1084,6 +1085,68 @@ find_mouse_window_for_ns_event (NSEvent *nsevent,
   return mouse_window;
 }
 
+/* Trigger crossing events if necessary. This is used when showing a new
+ * window, since the tracking rect API doesn't work reliably when a window
+ * shows up under the mouse cursor. It's done by finding the topmost window
+ * under the mouse pointer and synthesizing crossing events into that
+ * window.
+ */
+void
+_gdk_quartz_events_trigger_crossing_events (void)
+{
+  NSPoint point;
+  gint x; 
+  gint y;
+  GdkWindow *mouse_window;
+  GdkWindowImplQuartz *impl;
+  NSUInteger flags = 0;
+  NSTimeInterval timestamp = 0;
+  NSEvent *current_event;
+  NSEvent *nsevent;
+
+  point = [NSEvent mouseLocation];
+  x = point.x;
+  y = _gdk_quartz_window_get_inverted_screen_y (point.y);
+
+  mouse_window = _gdk_quartz_window_find_child (_gdk_root, x, y);
+  if (mouse_window == _gdk_root)
+    return;
+
+  /* NSMouseEntered always happens on the toplevel. */
+  mouse_window = gdk_window_get_toplevel (mouse_window);
+
+  get_converted_window_coordinates (_gdk_root,
+                                    x, y,
+                                    mouse_window,
+                                    &x, &y);
+
+  impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (mouse_window)->impl);
+
+  /* Fix up the event to be less fake if possible. */
+  current_event = [NSApp currentEvent];
+  if (current_event)
+    {
+      flags = [current_event modifierFlags];
+      timestamp = [current_event timestamp];
+    }
+
+  nsevent = [NSEvent otherEventWithType:NSApplicationDefined
+                               location:NSMakePoint(x, impl->height - y)
+                          modifierFlags:flags
+                              timestamp:timestamp
+                           windowNumber:[impl->toplevel windowNumber]
+                                context:nil
+                                subtype:GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
+                                  data1:0
+                                  data2:0];
+
+#ifdef G_ENABLE_DEBUG
+  /*_gdk_quartz_window_debug_highlight (mouse_window);*/
+#endif
+
+  synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
+}
+
 /* Synthesizes crossing events if necessary, based on the passed in
  * NSEvent. Uses NSMouseEntered and NSMouseExisted for toplevels and
  * the mouse moved/dragged events for child windows, to see if the
index b79663baa67f4681627e5fc4afa57bd2161f419d..39696ec11d59d1b5ef9ea4dda73bb5b8c6ec327f 100644 (file)
@@ -147,6 +147,11 @@ void       _gdk_quartz_window_did_resign_main       (GdkWindow *window);
 void       _gdk_quartz_window_debug_highlight       (GdkWindow *window);
 
 /* Events */
+typedef enum {
+  GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP,
+  GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
+} GdkQuartzEventSubType;
+
 void         _gdk_quartz_events_update_focus_window    (GdkWindow *new_window,
                                                         gboolean   got_focus);
 GdkWindow *  _gdk_quartz_events_get_mouse_window       (gboolean   consider_grabs);
@@ -154,6 +159,7 @@ void         _gdk_quartz_events_update_mouse_window    (GdkWindow *window);
 void         _gdk_quartz_events_update_cursor          (GdkWindow *window);
 void         _gdk_quartz_events_send_map_events        (GdkWindow *window);
 GdkEventMask _gdk_quartz_events_get_current_event_mask (void);
+void         _gdk_quartz_events_trigger_crossing_events(void);
 
 extern GdkWindow *_gdk_quartz_keyboard_grab_window;
 extern GdkWindow *_gdk_quartz_pointer_grab_window;
index 54238235b3fced9bd8c01529276f8d576e868399..d585f1d60403ac2341195f5516bcca84ed8052c0 100644 (file)
@@ -1101,6 +1101,9 @@ show_window_internal (GdkWindow *window,
   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
     _gdk_quartz_window_attach_to_parent (window);
 
+  if (impl->toplevel)
+    _gdk_quartz_events_trigger_crossing_events ();
+
   GDK_QUARTZ_RELEASE_POOL;
 }